//给你无向 连通 图中一个节点的引用，请你返回该图的 深拷贝（克隆）。 
//
// 图中的每个节点都包含它的值 val（int） 和其邻居的列表（list[Node]）。 
//
// 
//class Node {
//    public int val;
//    public List<Node> neighbors;
//} 
//
// 
//
// 测试用例格式： 
//
// 简单起见，每个节点的值都和它的索引相同。例如，第一个节点值为 1（val = 1），第二个节点值为 2（val = 2），以此类推。该图在测试用例中使用邻
//接列表表示。 
//
// 邻接列表 是用于表示有限图的无序列表的集合。每个列表都描述了图中节点的邻居集。 
//
// 给定节点将始终是图中的第一个节点（值为 1）。你必须将 给定节点的拷贝 作为对克隆图的引用返回。 
//
// 
//
// 示例 1： 
//
// 
//
// 
//输入：adjList = [[2,4],[1,3],[2,4],[1,3]]
//输出：[[2,4],[1,3],[2,4],[1,3]]
//解释：
//图中有 4 个节点。
//节点 1 的值是 1，它有两个邻居：节点 2 和 4 。
//节点 2 的值是 2，它有两个邻居：节点 1 和 3 。
//节点 3 的值是 3，它有两个邻居：节点 2 和 4 。
//节点 4 的值是 4，它有两个邻居：节点 1 和 3 。
// 
//
// 示例 2： 
//
// 
//
// 
//输入：adjList = [[]]
//输出：[[]]
//解释：输入包含一个空列表。该图仅仅只有一个值为 1 的节点，它没有任何邻居。
// 
//
// 示例 3： 
//
// 
//输入：adjList = []
//输出：[]
//解释：这个图是空的，它不含任何节点。
// 
//
// 
//
// 提示： 
//
// 
// 这张图中的节点数在 [0, 100] 之间。 
// 1 <= Node.val <= 100 
// 每个节点值 Node.val 都是唯一的， 
// 图中没有重复的边，也没有自环。 
// 图是连通图，你可以从给定节点访问到所有节点。 
// 
//
// Related Topics 深度优先搜索 广度优先搜索 图 哈希表 👍 715 👎 0


package LeetCode.editor.cn;

import java.util.*;

/**
 * @author ldltd
 * @date 2024-05-18 00:47:51
 * @description 133.克隆图
 */
public class CloneGraph{
	 public static void main(String[] args) {
	 	 //测试代码
	 	 CloneGraph fun=new CloneGraph();
	 	 Solution solution = fun.new Solution();
          Node node=new Node(1);

            Node node2=new Node(2);
         Node node3=new Node(3);
         Node node4=new Node(4);
         node.neighbors=new ArrayList<>();
            node2.neighbors=new ArrayList<>();
         node3.neighbors=new ArrayList<>();
         node4.neighbors=new ArrayList<>();
            node.neighbors.add(node2);
         node.neighbors.add(node4);
            node2.neighbors.add(node);
         node2.neighbors.add(node3);
            node3.neighbors.add(node2);
            node3.neighbors.add(node4);
            node4.neighbors.add(node);
            node4.neighbors.add(node3);
            Node res = solution.cloneGraph(node);
            System.out.println(res);
	 }

//力扣代码
//leetcode submit region begin(Prohibit modification and deletion)

// Definition for a Node.
 static class Node {
    public int val;
    public List<Node> neighbors;
    public Node() {
        val = 0;
        neighbors = new ArrayList<Node>();
    }
    public Node(int _val) {
        val = _val;
        neighbors = new ArrayList<Node>();
    }
    public Node(int _val, ArrayList<Node> _neighbors) {
        val = _val;
        neighbors = _neighbors;
    }
}


class Solution {
         /*深度优先，*/
    public Node cloneGraph(Node node) {
        if(node==null) return node;
        Deque<Node> q=new ArrayDeque<>();
        Node res=new Node();
        HashMap<Integer,Node> map=new HashMap<>();
        q.offer(node);
        map.put(node.val,res);
        while (!q.isEmpty()){
            Node poll = q.poll();
            Node ne=map.getOrDefault(poll.val,new Node(poll.val));
           ne.val=poll.val;
            if(!ne.neighbors.isEmpty()) continue;
            map.put(poll.val,ne);
            List<Node> neighbors = poll.neighbors;
            for (Node neighbor : neighbors) {
                if(map.get(neighbor.val)==null){
                    map.put(neighbor.val,new Node(neighbor.val));
                }
                if(map.get(neighbor.val).neighbors.isEmpty())
                    q.offer(neighbor);
                ne.neighbors.add(map.get(neighbor.val));
            }
        }
        return map.get(node.val);
    }
    /*广度优先*/
    private HashMap <Node, Node> visited = new HashMap <> ();
    public Node cloneGraph1(Node node) {
        if (node == null) {
            return node;
        }

        // 如果该节点已经被访问过了，则直接从哈希表中取出对应的克隆节点返回
        if (visited.containsKey(node)) {
            return visited.get(node);
        }

        // 克隆节点，注意到为了深拷贝我们不会克隆它的邻居的列表
        Node cloneNode = new Node(node.val, new ArrayList());
        // 哈希表存储
        visited.put(node, cloneNode);

        // 遍历该节点的邻居并更新克隆节点的邻居列表
        for (Node neighbor: node.neighbors) {
            cloneNode.neighbors.add(cloneGraph(neighbor));
        }
        return cloneNode;
    }

}
//leetcode submit region end(Prohibit modification and deletion)

}
